library ieee;

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package cpu_utils is

		constant unit_delay : Time := 1 ns;
		
		--type bool_to_bit_table is array (boolean) of bit;
		--constant bool_to_bit : bool_to_bit_table;
		--type bit_32_array is array (integer range <>) of bit_32;
		--function resolve_bit_32 (driver : in bit_32_array) return bit_32;
		--subtype bus_bit_32 is resolve_bit_32 bit_32;
		--subtype CC_bits is bit_vector(2 downto 0);
		--subtype cm_bits is bit_vector(3 downto 0);
		
		subtype bit_32 is bit_vector(31 downto 0);
		subtype bit_8 is bit_vector(7 downto 0);
		subtype bit_6 is bit_vector(5 downto 0);
		subtype bit_5 is bit_vector(4 downto 0);
		
		
		--opcodes:
		constant op_load : bit_6 := B"00_0000";
		constant op_store : bit_6 := B"10_0000";	
		constant op_mov : bit_6 := B"00_1000";
		constant op_movi : bit_6 := B"10_1000";		
		constant op_add : bit_6 := B"00_0100";
		constant op_sub : bit_6 := B"10_0100";
		constant op_addi : bit_6 := B"00_1100";
		constant op_subi : bit_6 := B"10_1100";	
		constant op_and : bit_6 := B"00_0010";
		constant op_or : bit_6 := B"10_0010";
		constant op_xor : bit_6 := B"01_0010";
		constant op_not : bit_6 := B"11_0010";	
		constant op_shl : bit_6 := B"00_0110";
		constant op_shr : bit_6 := B"10_0110";
		constant op_sar : bit_6 := B"01_0110";
		constant op_rol : bit_6 := B"11_0110";
		constant op_ror : bit_6 := B"00_1110";	
		constant op_jmp : bit_6 := B"00_0001";
		constant op_jsr : bit_6 := B"10_0001";
		constant op_rts : bit_6 := B"01_0001";
		constant op_push : bit_6 := B"00_1001";
		constant op_pop : bit_6 := B"10_1001";	
		constant op_beq : bit_6 := B"00_0101";
		constant op_bnq : bit_6 := B"10_0101";
		constant op_bgt : bit_6 := B"01_0101";
		constant op_blt : bit_6 := B"11_0101";
		constant op_bge : bit_6 := B"00_1101";
		constant op_ble : bit_6 := B"10_1101";
		constant op_halt : bit_6 := B"00_0011";
		
		
	
		
		--conversion functions:
		
		--int: integer to be converted
		--size_of_bv: number of pins that are available for representation of an integer 
		function to_bits(int: in integer; size_of_bv: in integer) return bit_vector;
		
		function to_bits(value: in unsigned; size_of_bv: in integer) return bit_vector;
		function to_bits(value: in signed; size_of_bv: in integer) return bit_vector;
		
		function to_std_logic_vector(value: in integer; size: in integer) return std_logic_vector;
		
		--bv: bit_vector to be represented as an integer
		function to_integer(bv: in bit_vector) return integer;
		function to_integer(slv: in std_logic_vector) return integer;
		
		function to_signed(bv: in bit_vector) return signed;
		function to_unsigned(bv: in bit_vector) return unsigned;
		--incrementation of a bit vector:
		function inc_bit_vector(bits: in bit_vector) return bit_vector;
		
end cpu_utils;



package body cpu_utils is

	
	function inc_bit_vector(bits: in bit_vector) return bit_vector is
		variable a: bit_vector(bits'range);
		variable carry_bit: bit;
	begin
		carry_bit:='1';
		for i in bits'low to bits'high loop
			a(i) := bits(i) xor carry_bit;
			carry_bit := bits(i) and carry_bit;
		end loop;
			
		return a;
	end inc_bit_vector;
	
	
	function to_bits(int: in integer; size_of_bv: in integer) return bit_vector is
	begin
		return to_bitvector(std_logic_vector(to_unsigned(int, size_of_bv)));
	end;
	
	function to_bits(value: in unsigned; size_of_bv: in integer) return bit_vector is
	begin
		return to_bitvector(std_logic_vector(value));
	end;
	
	function to_bits(value: in signed; size_of_bv: in integer) return bit_vector is
	begin
		return to_bitvector(std_logic_vector(value));
	end;
	
	function to_std_logic_vector(value: in integer; size: in integer) return std_logic_vector is
	begin
		return std_logic_vector(to_signed(value, size));
	end;
	
	
	function to_integer (bv: in bit_vector) return integer is
	begin
		return to_integer(unsigned(to_stdlogicvector(bv)));
	end;
	
	function to_integer(slv: in std_logic_vector) return integer is
	begin
		return to_integer(signed(slv));
	end;
	
	function to_signed(bv: in bit_vector) return signed is
	begin
		return signed(to_stdlogicvector(bv));
	end;
	
	function to_unsigned(bv: in bit_vector) return unsigned is
	begin
		return unsigned(to_stdlogicvector(bv));
	end;
		
	
end cpu_utils;